package com.allen.app.common.config.aspect;

import com.allen.app.common.config.other.BusinessException;
import java.lang.reflect.Method;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;


/**
 * Description: 重复请求切面控制
 *
 * @author Limiaojun
 * @date 2019/8/1 15:37
 **/
@Aspect
@Component
@Slf4j
public class ManyRequestAspect {

    private final ValueOperations<String,Object> redisValueOperations;

    public ManyRequestAspect(ValueOperations<String,Object> redisValueOperations) {
        this.redisValueOperations = redisValueOperations;
    }

    @Around("@annotation(manyRequest)")
    public Object arround(ProceedingJoinPoint pjp, ManyRequest manyRequest) throws Throwable {
        //如果开关未开启,不执行aop处理
        if (Objects.isNull(manyRequest) ||  !manyRequest.enabled()) {
            return pjp.proceed();
        }

        //防止单人连续点击的幂等处理
        Method method = ((MethodSignature) pjp.getSignature()).getMethod();
        String name = AcpectCommonUtils.parseKey(manyRequest.name(), method, pjp.getArgs());
        name = "aspect:ManyRequest:"+name;
        log.info("manyRequest start:\t{}", name);
        Boolean ret = redisValueOperations.setIfAbsent(name, "", manyRequest.leaseTime(), manyRequest.timeUnit());
        if(Objects.equals(ret,false)){
            Long expire = redisValueOperations.getOperations().getExpire(name);
            String msg = String.format("请不要重复点击,%s秒钟之后再试",expire);
            log.warn(msg);

            throw new BusinessException("接口处理中,请稍后再试!").isSendDingTalk(false).isPrintLog(false);
        }
        Object proceed = pjp.proceed();
        //接口执行完毕清空缓存
        redisValueOperations.getOperations().expire(name, 0, manyRequest.timeUnit());
        return proceed;
    }

}